home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / bin / xtras / addon2.c < prev    next >
C/C++ Source or Header  |  1994-09-11  |  21KB  |  873 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  e-mail: dieter@cip.e-technik.uni-erlangen.de
  18. *  CIS: 100255.3074
  19. *
  20. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  21. *
  22. *  The vista projection was taken from:
  23. *
  24. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  25. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  26. *    Projection Image", New Advances in Computer Graphics, Proceedings
  27. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  28. *    Springer, ..., pp. 549-560
  29. *
  30. *  The idea for the light buffer was taken from:
  31. *
  32. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  33. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  34. *
  35. *****************************************************************************/
  36.  
  37. /****************************************************************************
  38. *  addon2.c
  39. *
  40. *  This module was written by Dieter Bayer.
  41. *
  42. *  This module contains functions used only for the light buffer.
  43. *
  44. *  01.03.1994 : Creation
  45. *
  46. *  29.04.1994 : Creation
  47. *
  48. ******************************************************************************/
  49.  
  50. #include "frame.h"
  51. #include "vector.h"
  52. #include "povproto.h"
  53. #include "addon.h"
  54.  
  55. #ifdef DB_CODE
  56.  
  57.  
  58. /*****************************************************************************
  59. * External variables
  60. ******************************************************************************/
  61.  
  62. extern FRAME Frame;
  63. extern unsigned long Quality_Flags;
  64. extern unsigned int Options, Extended_Options;
  65.  
  66. extern METHODS Bicubic_Patch_Methods;
  67. extern METHODS Blob_Methods;
  68. extern METHODS Box_Methods;
  69. extern METHODS Cone_Methods;
  70. extern METHODS Csg_Height_Field_Methods;
  71. extern METHODS CSG_Intersection_Methods;
  72. extern METHODS CSG_Merge_Methods;
  73. extern METHODS CSG_Union_Methods;
  74. extern METHODS Disc_Methods;
  75. extern METHODS Ellipsoid_Methods;
  76. extern METHODS Height_Field_Methods;
  77. extern METHODS Light_Source_Methods;
  78. extern METHODS Plane_Methods;
  79. extern METHODS Poly_Methods;
  80. extern METHODS Quadric_Methods;
  81. extern METHODS Smooth_Triangle_Methods;
  82. extern METHODS Sphere_Methods;
  83. extern METHODS Triangle_Methods;
  84.  
  85. extern OBJECT *Root_Object;
  86.  
  87. extern size_t Mem_Light_Buffers;
  88.  
  89.  
  90.  
  91. /*****************************************************************************
  92. * static variabls
  93. ******************************************************************************/
  94.  
  95. static VECTOR VIEW_VX1 = {-0.7071067812, 0.0, -0.7071067812};
  96. static VECTOR VIEW_VX2 = { 0.7071067812, 0.0, -0.7071067812};
  97. static VECTOR VIEW_VY1 = {0.0, -0.7071067812, -0.7071067812};
  98. static VECTOR VIEW_VY2 = {0.0,  0.7071067812, -0.7071067812};
  99. static DBL VIEW_DX1 = 0.0;
  100. static DBL VIEW_DX2 = 0.0;
  101. static DBL VIEW_DY1 = 0.0;
  102. static DBL VIEW_DY2 = 0.0;
  103.  
  104.  
  105.  
  106. /*****************************************************************************
  107. * static functions
  108. ******************************************************************************/
  109.  
  110. static void Calc_Points PARAMS((int Axis, OBJECT *Object, int *Number, VECTOR *Points, VECTOR *Origin));
  111.  
  112. static int BBox_Invisible PARAMS((int Axis, BBOX *Bounds, VECTOR *Origin));
  113.  
  114. static void Project_rectangle PARAMS((PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, VECTOR P4, int *visible));
  115. static void Project_triangle PARAMS((PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, int *visible));
  116. static void Project_Bbox PARAMS((PROJECT *Project, VECTOR *Points, int *visible));
  117. static void Project_Object PARAMS((PROJECT *Project, OBJECT *Object, int Axis, VECTOR *Origin));
  118.  
  119. static void Project_Bounding_Slab
  120.   PARAMS((int Axis, VECTOR *Origin, PROJECT *Project,
  121.       PROJECT_TREE_NODE **Entry, OBJECT *Object));
  122.  
  123.  
  124. /*****************************************************************************
  125. *
  126. * FUNCTION      : Calc_Points
  127. *
  128. * ARGUMENTS     : Axis   - Axis along the objects will be projected
  129. *                 Object - Object
  130. *                 Number - Number of points to project
  131. *                 Points - Points to project
  132. *                 Origin - Origin of current light source
  133. *
  134. * MODIFIED ARGS : Number, Points
  135. *
  136. * RETURN VALUE  : none
  137. *
  138. * AUTHOR        : Dieter Bayer, May 1994
  139. *
  140. * DESCRIPTION
  141. *
  142. *   Calculate the points to project depending on the object type,
  143. *   the light source position and the axis.
  144. *
  145. * CHANGES
  146. *
  147. *   -
  148. *
  149. ******************************************************************************/
  150.  
  151. static void Calc_Points(Axis, Object, Number, Points, Origin)
  152. int Axis;
  153. OBJECT *Object;
  154. int *Number;
  155. VECTOR *Points, *Origin;
  156. {
  157.   register int i;
  158.   DBL Direction;
  159.   VECTOR P[8];
  160.  
  161.   /* Get points depending on object's type */
  162.  
  163.   if ((Object->Methods == &Triangle_Methods) ||
  164.       (Object->Methods == &Smooth_Triangle_Methods))
  165.   {
  166.     if (Object->Methods == &Triangle_Methods)
  167.     {
  168.       *Number = 3;
  169.       P[0] = ((TRIANGLE *)Object)->P1;
  170.       P[1] = ((TRIANGLE *)Object)->P2;
  171.       P[2] = ((TRIANGLE *)Object)->P3;
  172.     }
  173.     if (Object->Methods == &Smooth_Triangle_Methods)
  174.     {
  175.       *Number = 3;
  176.       P[0] = ((SMOOTH_TRIANGLE *)Object)->P1;
  177.       P[1] = ((SMOOTH_TRIANGLE *)Object)->P2;
  178.       P[2] = ((SMOOTH_TRIANGLE *)Object)->P3;
  179.     }
  180.   }
  181.   else
  182.   {
  183.     *Number = 8;
  184.  
  185.     for (i = 0; i < *Number; i++)
  186.     {
  187.       P[i] = Object->Bounds.Lower_Left;
  188.  
  189.       P[i].x += ((i & 1) ? Object->Bounds.Lengths.x : 0.0);
  190.       P[i].y += ((i & 2) ? Object->Bounds.Lengths.y : 0.0);
  191.       P[i].z += ((i & 4) ? Object->Bounds.Lengths.z : 0.0);
  192.     }
  193.   }
  194.  
  195.   /* The points' coordinates need to be relative to the light source */
  196.  
  197.   for (i = 0; i < *Number; i++)
  198.   {
  199.     P[i].x -= Origin->x;
  200.     P[i].y -= Origin->y;
  201.     P[i].z -= Origin->z;
  202.   }
  203.  
  204.   /* Switch axes so that the specified axis becomes the +Z-axis */
  205.  
  206.   if ((Axis == XaxisP) || (Axis == YaxisP) || (Axis == ZaxisP))
  207.   {
  208.     Direction = +1.0;
  209.   }
  210.   else
  211.   {
  212.     Direction = -1.0;
  213.   }
  214.  
  215.   /* Modify points so that the new z direction is the projection axis */
  216.  
  217.   switch (Axis)
  218.   {
  219.     case XaxisP :
  220.     case XaxisM :
  221.  
  222.       for (i = 0; i < *Number; i++)
  223.       {
  224.     Points[i].x = P[i].y;
  225.     Points[i].y = P[i].z;
  226.     Points[i].z = P[i].x * Direction;
  227.       }
  228.       break;
  229.  
  230.     case YaxisP :
  231.     case YaxisM :
  232.  
  233.       for (i = 0; i < *Number; i++)
  234.       {
  235.     Points[i].x = P[i].x;
  236.     Points[i].y = P[i].z;
  237.     Points[i].z = P[i].y * Direction;
  238.       }
  239.       break;
  240.  
  241.     case ZaxisP :
  242.     case ZaxisM :
  243.  
  244.       for (i = 0; i < *Number; i++)
  245.       {
  246.     Points[i].x = P[i].x;
  247.     Points[i].y = P[i].y;
  248.     Points[i].z = P[i].z * Direction;
  249.       }
  250.       break;
  251.  
  252.     default :
  253.       Fatal_Error("Illegal axis in module addon2.\n");
  254.   }
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************
  260. *
  261. * FUNCTION      : BBox_Invisible
  262. *
  263. * ARGUMENTS     : Axis   - Axis along the objects will be projected
  264. *                 Bounds - Bounding box to test
  265. *                 Origin - Origin of current light source
  266. *
  267. * MODIFIED ARGS : none
  268. *
  269. * RETURN VALUE  : int - Flag if bounding box is totally invisble
  270. *
  271. * AUTHOR        : Dieter Bayer, May 1994
  272. *
  273. * DESCRIPTION
  274. *
  275. *   Do a quick test if a bounding box is totally invisble from the
  276. *   current light source in the specified axis direction.
  277. *
  278. * CHANGES
  279. *
  280. *   -
  281. *
  282. ******************************************************************************/
  283.  
  284. static int BBox_Invisible(Axis, Bounds, Origin)
  285. int Axis;
  286. BBOX *Bounds;
  287. VECTOR *Origin;
  288. {
  289.   switch (Axis)
  290.   {
  291.     case XaxisP :
  292.  
  293.       if (Bounds->Lower_Left.x + Bounds->Lengths.x < Origin->x) return(TRUE);
  294.       break;
  295.  
  296.     case XaxisM :
  297.  
  298.       if (Bounds->Lower_Left.x > Origin->x) return(TRUE);
  299.       break;
  300.  
  301.     case YaxisP :
  302.  
  303.       if (Bounds->Lower_Left.y + Bounds->Lengths.y < Origin->y) return(TRUE);
  304.       break;
  305.  
  306.     case YaxisM :
  307.  
  308.       if (Bounds->Lower_Left.y > Origin->y) return(TRUE);
  309.       break;
  310.  
  311.     case ZaxisP :
  312.  
  313.       if (Bounds->Lower_Left.z + Bounds->Lengths.z < Origin->z) return(TRUE);
  314.       break;
  315.  
  316.     case ZaxisM :
  317.  
  318.       if (Bounds->Lower_Left.z > Origin->z) return(TRUE);
  319.       break;
  320.  
  321.     default :
  322.       Fatal_Error("Illegal axis in module addon2.\n");
  323.   }
  324.  
  325.   return(FALSE);
  326. }
  327.  
  328.  
  329.  
  330. /*****************************************************************************
  331. *
  332. * FUNCTION      : Project_rectangle
  333. *
  334. * ARGUMENTS     : Project        - Rectangle's projection
  335. *                 P1, P2, P3, P4 - Rectangle's edges
  336. *                 visible        - Flag if rectangle is visible
  337. *
  338. * MODIFIED ARGS : Project, visible
  339. *
  340. * RETURN VALUE  : none
  341. *
  342. * AUTHOR        : Dieter Bayer, May 1994
  343. *
  344. * DESCRIPTION
  345. *
  346. *   Project a rectangle onto a light source.
  347. *
  348. * CHANGES
  349. *
  350. *   -
  351. *
  352. ******************************************************************************/
  353.  
  354. static void Project_rectangle(Project, P1, P2, P3, P4, visible)
  355. PROJECT *Project;
  356. VECTOR P1, P2, P3, P4;
  357. int *visible;
  358. {
  359.   VECTOR Points[MAX_CLIP_POINTS];
  360.   int i, number;
  361.   int x, y;
  362.  
  363.   /* Square totally invisible? */
  364.  
  365.   if ((P1.z <= 0.0) && (P2.z <= 0.0) && (P3.z <= 0.0) && (P4.z <= 0.0))
  366.     return;
  367.  
  368.   Points[0] = P1;
  369.   Points[1] = P2;
  370.   Points[2] = P3;
  371.   Points[3] = P4;
  372.  
  373.   number = 4;
  374.  
  375.   /* Clip square only if some quick tests say it's necessary.
  376.      Assuming that only a few squares need clipping this saves some time.
  377.      (I don't need to write fabs(P?.z) since the tests succeed anyway
  378.       if P?.z < 0. Hope the compiler doesn't change the tests' order!) */
  379.  
  380.   if ((P1.z < 0.0) || (P2.z < 0.0) || (P3.z < 0.0) || (P4.z < 0.0) ||
  381.       (fabs(P1.x) > (P1.z)) || (fabs(P1.y) > (P1.z)) ||
  382.       (fabs(P2.x) > (P2.z)) || (fabs(P2.y) > (P2.z)) ||
  383.       (fabs(P3.x) > (P3.z)) || (fabs(P3.y) > (P3.z)) ||
  384.       (fabs(P4.x) > (P4.z)) || (fabs(P4.y) > (P4.z)))
  385.   {
  386.     Clip_Polygon(Points, &number, &VIEW_VX1, &VIEW_VX2, &VIEW_VY1, &VIEW_VY2,
  387.                  VIEW_DX1,  VIEW_DX2,  VIEW_DY1,  VIEW_DY2);
  388.   }
  389.  
  390.   if (!number)
  391.     return;
  392.  
  393.   for (i = 0; i < number; i++)
  394.   {
  395.     if (Points[i].z < EPSILON)
  396.     {
  397.       Points[i].x = Points[i].y = 0.0;
  398.     }
  399.     else
  400.     {
  401.       Points[i].x = Points[i].x / Points[i].z;
  402.       Points[i].y = Points[i].y / Points[i].z;
  403.       if (fabs(Points[i].x) < EPSILON) Points[i].x = 0.0;
  404.       if (fabs(Points[i].y) < EPSILON) Points[i].y = 0.0;
  405.     }
  406.  
  407.     x = (int)(MAX_LB_ENTRY * Points[i].x);
  408.     y = (int)(MAX_LB_ENTRY * Points[i].y);
  409.  
  410.     if (x < Project->x1) Project->x1 = x;
  411.     if (x > Project->x2) Project->x2 = x;
  412.     if (y < Project->y1) Project->y1 = y;
  413.     if (y > Project->y2) Project->y2 = y;
  414.   }
  415.  
  416.   *visible = TRUE;
  417. }
  418.  
  419.  
  420.  
  421.  
  422. /*****************************************************************************
  423. *
  424. * FUNCTION      : Project_triangle
  425. *
  426. * ARGUMENTS     : Project    - Triangle's projection
  427. *                 P1, P2, P3 - Triangles's edges
  428. *                 visible    - Flag if triangle is visible
  429. *
  430. * MODIFIED ARGS : Project, visible
  431. *
  432. * RETURN VALUE  : none
  433. *
  434. * AUTHOR        : Dieter Bayer, May 1994
  435. *
  436. * DESCRIPTION
  437. *
  438. *   Project a triangle onto a light source.
  439. *
  440. * CHANGES
  441. *
  442. *   -
  443. *
  444. ******************************************************************************/
  445.  
  446. static void Project_triangle(Project, P1, P2, P3, visible)
  447. PROJECT *Project;
  448. VECTOR P1, P2, P3;
  449. int *visible;
  450. {
  451.   VECTOR Points[MAX_CLIP_POINTS];
  452.   int i, number;
  453.   int x, y;
  454.  
  455.   /* Triangle totally invisible? */
  456.  
  457.   if ((P1.z <= 0.0) && (P2.z <= 0.0) && (P3.z <= 0.0))
  458.     return;
  459.  
  460.   Points[0] = P1;
  461.   Points[1] = P2;
  462.   Points[2] = P3;
  463.  
  464.   number = 3;
  465.  
  466.   /* Clip triangle only if some quick tests say it's necessary.
  467.      Assuming that only a few triangles need clipping this saves some time.
  468.      (I don't need to write fabs(P?.z) since the tests succeed anyway
  469.       if P?.z < 0. Hope the compiler doesn't change the tests' order!) */
  470.  
  471.   if ((P1.z < 0.0) || (P2.z < 0.0) || (P3.z < 0.0) ||
  472.       (fabs(P1.x) > (P1.z)) || (fabs(P1.y) > (P1.z)) ||
  473.       (fabs(P2.x) > (P2.z)) || (fabs(P2.y) > (P2.z)) ||
  474.       (fabs(P3.x) > (P3.z)) || (fabs(P3.y) > (P3.z)))
  475.   {
  476.     Clip_Polygon(Points, &number, &VIEW_VX1, &VIEW_VX2, &VIEW_VY1, &VIEW_VY2,
  477.                    VIEW_DX1,  VIEW_DX2,  VIEW_DY1,  VIEW_DY2);
  478.   }
  479.  
  480.   if (!number)
  481.     return;
  482.  
  483.   for (i = 0; i < number; i++)
  484.   {
  485.     if (fabs(Points[i].z) < EPSILON)
  486.     {
  487.       Points[i].x = Points[i].y = 0.0;
  488.     }
  489.     else
  490.     {
  491.       Points[i].x = Points[i].x / Points[i].z;
  492.       Points[i].y = Points[i].y / Points[i].z;
  493.       if (fabs(Points[i].x) < EPSILON) Points[i].x = 0.0;
  494.       if (fabs(Points[i].y) < EPSILON) Points[i].y = 0.0;
  495.     }
  496.  
  497.     x = (int)(MAX_LB_ENTRY * Points[i].x);
  498.     y = (int)(MAX_LB_ENTRY * Points[i].y);
  499.  
  500.     if (x < Project->x1) Project->x1 = x;
  501.     if (x > Project->x2) Project->x2 = x;
  502.     if (y < Project->y1) Project->y1 = y;
  503.     if (y > Project->y2) Project->y2 = y;
  504.   }
  505.  
  506.   *visible = TRUE;
  507. }
  508.  
  509.  
  510.  
  511.  
  512. /*****************************************************************************
  513. *
  514. * FUNCTION      : Project_BBox
  515. *
  516. * ARGUMENTS     : Project - Box's projection
  517. *                 Points  - Box's edges
  518. *                 visible - Flag if box is visible
  519. *
  520. * MODIFIED ARGS : Project, visible
  521. *
  522. * RETURN VALUE  : none
  523. *
  524. * AUTHOR        : Dieter Bayer, May 1994
  525. *
  526. * DESCRIPTION
  527. *
  528. *   Project a box onto a light source.
  529. *
  530. * CHANGES
  531. *
  532. *   -
  533. *
  534. ******************************************************************************/
  535.  
  536. static void Project_Bbox(Project, Points, visible)
  537. PROJECT *Project;
  538. VECTOR *Points;
  539. int *visible;
  540. {
  541.   Project_rectangle(Project, Points[0], Points[1], Points[3], Points[2], visible);
  542.   Project_rectangle(Project, Points[4], Points[5], Points[7], Points[6], visible);
  543.   Project_rectangle(Project, Points[0], Points[1], Points[5], Points[4], visible);
  544.   Project_rectangle(Project, Points[2], Points[3], Points[7], Points[6], visible);
  545.   Project_rectangle(Project, Points[1], Points[3], Points[7], Points[5], visible);
  546.   Project_rectangle(Project, Points[0], Points[2], Points[6], Points[4], visible);
  547. }
  548.  
  549.  
  550.  
  551. /*****************************************************************************
  552. *
  553. * FUNCTION      : Project_Object
  554. *
  555. * ARGUMENTS     : Object   - Object to project
  556. *                 Project  - Projection
  557. *
  558. * MODIFIED ARGS : Project
  559. *
  560. * RETURN VALUE  : none
  561. *
  562. * AUTHOR        : Dieter Bayer, May 1994
  563. *
  564. * DESCRIPTION
  565. *
  566. *   Get the projection of a single object onto a light source.
  567. *
  568. * CHANGES
  569. *
  570. *   -
  571. *
  572. ******************************************************************************/
  573.  
  574. static void Project_Object(Project, Object, Axis, Origin)
  575. PROJECT *Project;
  576. OBJECT *Object;
  577. int Axis;
  578. VECTOR *Origin;
  579. {
  580.   int visible, Number;
  581.   DBL Volume;
  582.   VECTOR Points[8];
  583.  
  584.   /* Do not project infinite objects (always visible!) */
  585.  
  586.   BOUNDS_VOLUME(Volume, Object->Bounds);
  587.  
  588.   if (Volume > INFINITE_VOLUME)
  589.   {
  590.     Project->x1 = Project->y1 = MIN_LB_ENTRY;
  591.     Project->x2 = Project->y2 = MAX_LB_ENTRY;
  592.     return;
  593.   }
  594.  
  595.   /* Get points to project */
  596.  
  597.   Calc_Points(Axis, Object, &Number, &Points[0], Origin);
  598.  
  599.   visible = FALSE;
  600.  
  601.   Project->x1 = Project->y1 = MAX_LB_ENTRY;
  602.   Project->x2 = Project->y2 = MIN_LB_ENTRY;
  603.  
  604.   if (Number == 3)
  605.   {
  606.     Project_triangle(Project, Points[0], Points[1], Points[2], &visible);
  607.   }
  608.   else
  609.   {
  610.     Project_Bbox(Project, &Points[0], &visible);
  611.   }
  612.  
  613.   if (!visible)
  614.   {
  615.     /* Object is invisible */
  616.  
  617.     Project->x1 = Project->y1 = MAX_LB_ENTRY;
  618.     Project->x2 = Project->y2 = MIN_LB_ENTRY;
  619.   }
  620.   else
  621.   {
  622.     /* We don't want to miss something */
  623.  
  624.     Project->x1--;
  625.     Project->x2++;
  626.     Project->y1--;
  627.     Project->y2++;
  628.   }
  629.  
  630.   Print_Point(6 * POINT_MOD);
  631. }
  632.  
  633.  
  634.  
  635. /*****************************************************************************
  636. *
  637. * FUNCTION      : Project_Bounding_Slab
  638. *
  639. * ARGUMENTS     : Axis     - Axis along the objects will be projected
  640. *                 Origin   - Origin of current light source
  641. *                 Project  - Projection
  642. *                 Tree     - Current node/leaf
  643. *                 Object   - Node/leaf in bounding slab hierarchy
  644. *
  645. * MODIFIED ARGS : Project, Tree
  646. *
  647. * RETURN VALUE  : none
  648. *
  649. * AUTHOR        : Dieter Bayer, May 1994
  650. *
  651. * DESCRIPTION
  652. *
  653. *   Project the bounding slab hierarchy onto a light source and thus create
  654. *   the light buffer hierarchy for this light source.
  655. *
  656. * CHANGES
  657. *
  658. *   -
  659. *
  660. ******************************************************************************/
  661.  
  662. static void Project_Bounding_Slab(Axis, Origin, Project, Tree, Object)
  663. int Axis;
  664. VECTOR *Origin;
  665. PROJECT *Project;
  666. PROJECT_TREE_NODE **Tree;
  667. OBJECT *Object;
  668. {
  669.   unsigned short int i;
  670.   COMPOSITE *Comp;
  671.   PROJECT Temp;
  672.   PROJECT_TREE_LEAF *Leaf;
  673.   PROJECT_TREE_NODE New;
  674.  
  675.   /* If the node is totally invisible we are ready */
  676.  
  677.   if (BBox_Invisible(Axis, &Object->Bounds, Origin))
  678.   {
  679.     return;
  680.   }
  681.  
  682.   if (Object->Type & BOUNDING_OBJECT)
  683.   {
  684.     /* Current object is a bounding object, i.e. a node in the slab tree */
  685.  
  686.     Comp = (COMPOSITE *)Object;
  687.  
  688.     /* Init new entry */
  689.  
  690.     New.Entries = 0;
  691.  
  692.     New.Object = Object;
  693.  
  694.     New.Project.x1 = New.Project.y1 = MAX_VB_ENTRY;
  695.     New.Project.x2 = New.Project.y2 = MIN_VB_ENTRY;
  696.  
  697.     /* Allocate temporary memory for node/leaf entries. */
  698.  
  699.     if ((New.Entry = (PROJECT_TREE_NODE **)malloc(Comp->Entries*sizeof(PROJECT_TREE_NODE *))) == NULL)
  700.     {
  701.       Fatal_Error("temporary tree entry");
  702.     }
  703.  
  704.     /* This is no leaf */
  705.  
  706.     New.is_leaf = FALSE;
  707.  
  708.     /* Get new entry, i.e. project bounding slab's entries */
  709.  
  710.     for (i = 0; i < Comp->Entries; i++)
  711.     {
  712.       New.Entry[i] = NULL;
  713.  
  714.       Project_Bounding_Slab(Axis, Origin, &Temp, &New.Entry[New.Entries],
  715.     Comp->Objects[i]);
  716.  
  717.       /* Use only visible entries */
  718.  
  719.       if (New.Entry[New.Entries] != NULL)
  720.       {
  721.     New.Project.x1 = min(New.Project.x1, Temp.x1);
  722.     New.Project.x2 = max(New.Project.x2, Temp.x2);
  723.     New.Project.y1 = min(New.Project.y1, Temp.y1);
  724.     New.Project.y2 = max(New.Project.y2, Temp.y2);
  725.  
  726.     New.Entries++;
  727.       }
  728.     }
  729.  
  730.     /* If there are any visible entries, we'll use them. */
  731.  
  732.     if (New.Entries > 0)
  733.     {
  734.       /* If there's only one entry, we won't need a new node. */
  735.  
  736.       if (New.Entries == 1)
  737.       {
  738.     *Tree    = New.Entry[0];
  739.     *Project = New.Project;
  740.       }
  741.       else
  742.       {
  743.     /* Allocate memory for new node in the light tree (never freed!)  */
  744.  
  745.     *Tree = (PROJECT_TREE_NODE *)LB_malloc(sizeof(PROJECT_TREE_NODE));
  746.  
  747.     if (*Tree == NULL)
  748.     {
  749.       Fatal_MAError("light tree node");
  750.     }
  751.  
  752.     **Tree = New;
  753.  
  754.         /* Allocate memory for node/leaf entries. */
  755.  
  756.         (*Tree)->Entry = (PROJECT_TREE_NODE **)VB_malloc(New.Entries*sizeof(PROJECT_TREE_NODE *));
  757.  
  758.     if ((*Tree)->Entry == NULL)
  759.     {
  760.       Fatal_MAError("vista tree node");
  761.     }
  762.  
  763.         memcpy((*Tree)->Entry, New.Entry, New.Entries*sizeof(PROJECT_TREE_NODE *));
  764.  
  765.     *Project = New.Project;
  766.       }
  767.     }
  768.   }
  769.   else
  770.   {
  771.     /* Current object is a normal object, i.e. a leaf in the slab tree */
  772.  
  773.     /* Project object onto light source */
  774.  
  775.     Project_Object(Project, Object, Axis, Origin);
  776.  
  777.     /* Is the object visible? */
  778.  
  779.     if ((Project->x1 <= Project->x2) && (Project->y1 <= Project->y2))
  780.     {
  781.       /* Allocate memory for new leaf in the light tree (never freed!)  */
  782.  
  783.       *Tree = (PROJECT_TREE_NODE *)LB_malloc(sizeof(PROJECT_TREE_LEAF));
  784.  
  785.       if (*Tree == NULL)
  786.       {
  787.     Fatal_MAError("light tree leaf");
  788.       }
  789.  
  790.       /* Init new leaf */
  791.  
  792.       Leaf = (PROJECT_TREE_LEAF *)(*Tree);
  793.  
  794.       Leaf->Object = Object;
  795.  
  796.       Leaf->Project = *Project;
  797.  
  798.       /* Yes, this is a leaf */
  799.  
  800.       Leaf->is_leaf = TRUE;
  801.     }
  802.   }
  803. }
  804.  
  805.  
  806.  
  807. /*****************************************************************************
  808. *
  809. * FUNCTION      : Build_Light_Buffers
  810. *
  811. * ARGUMENTS     : none
  812. *
  813. * MODIFIED ARGS : none
  814. *
  815. * RETURN VALUE  : none
  816. *
  817. * AUTHOR        : Dieter Bayer, May 1994
  818. *
  819. * DESCRIPTION
  820. *
  821. *   Build the light buffers, i.e. the 2d representations of the bounding slab
  822. *   hierarchy seen from the light sources.
  823. *
  824. * CHANGES
  825. *
  826. *   -
  827. *
  828. ******************************************************************************/
  829.  
  830. void Build_Light_Buffers()
  831. {
  832.   int i = 0, Axis;
  833.   PROJECT Project;
  834.   LIGHT_SOURCE *Light;
  835.  
  836.   /* Shadows aren't calculated --> return */
  837.  
  838.   if (!(Quality_Flags & Q_SHADOW))
  839.     return;
  840.  
  841.   /* We don't want a light buffer --> return */
  842.  
  843.   if (!(Extended_Options & USE_LIGHT_BUFFER))
  844.     return;
  845.  
  846.   /* Build the light buffer for all point(!) light sources */
  847.  
  848.   for (Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source)
  849.   {
  850.     if (!Light->Area_Light)
  851.     {
  852.       fprintf(stderr, "Building light buffer %d", ++i);
  853.  
  854.       Begin_Point();
  855.  
  856.       /* Project bounding slabs on all six sides */
  857.  
  858.       for (Axis = 0; Axis < 6; Axis++)
  859.       {
  860.     Light->Light_Buffer[Axis] = NULL;
  861.  
  862.     Project_Bounding_Slab(Axis, &Light->Center, &Project,
  863.       &Light->Light_Buffer[Axis], Root_Object);
  864.       }
  865.  
  866.       End_Point();
  867.     }
  868.   }
  869. }
  870.  
  871. #endif
  872.  
  873.